#include "PlayLayer.h"
#include "PokerLogic.h"
#include "PokerPlayer.h"
#include "CardUI.h"
#include "GameOverUI.h"
#include "DialogManager.h"
#include "InfoDetailUI.h"

// 数据备份，用于战局保存和回放
std::vector< int32_t > rec_card; // 手牌
extern uint8_t rec_bose; // 谁是地主
extern std::vector< std::tuple<uint8_t, std::vector< int32_t >, std::vector< int32_t > > > rec_out; // 每一轮出牌的信息

PlayLayer::PlayLayer() : IDialog()
{
    RegDialogCtrl("Image_bg_game", imgBg);
    RegDialogCtrl("Panel_OP", m_opGroup);
    RegDialogCtrl("Panel_Start", m_initGroup);
    RegDialogCtrl("BtnStart", m_btnStart);
    RegDialogCtrl("BtnMaster", m_btnMaster);//叫地主
    RegDialogCtrl("BtnSkip", m_btnSkip);//不叫
    RegDialogCtrl("BtnIgnore", m_btnIgnore);//不出
    RegDialogCtrl("BtnReset", m_btnReset);//重选
    RegDialogCtrl("BtnTipCard", m_btnTipCard);//提示
    RegDialogCtrl("BtnPostCard", m_btnPostCard);//出牌
    RegDialogCtrl("CardZone", m_cardZone);
}

PlayLayer::~PlayLayer(){
}

void PlayLayer::onPlayerAction(const PokerPlayer * const thePlayer, PLAYER_STATE state, int32_t card) {
    static std::vector< int32_t > data;
    uint8_t seat = thePlayer->getSeat();
    if(state == PLAYER_STATE::ON_CARD_IN) {
        if(seat == 0) {
            SimpleAudioEngine::getInstance()->playEffect("sound/sendcard.mp3");
        }
    } else if (state == PLAYER_STATE::ON_CARD_OUT_START) {
        m_opGroup->setVisible(seat == 0);
        // 战局保存 Start
        thePlayer->getHandCards(rec_card);// 给空表填入数据
        // 战局保存 End
        if(seat == 0) {
            // 拉到上家出的牌
            std::vector< int32_t > cardsLastOut;
            uint8_t theSeat = PokerLogic::shard()->getRealSeat(seat, -1);
            PokerLogic::shard()->getPlayer(theSeat)->getLastOutCards(cardsLastOut);
            if (cardsLastOut.empty()) {
                // 上家没出? 再找上上家看看
                theSeat = PokerLogic::shard()->getRealSeat(seat, -2);
                PokerLogic::shard()->getPlayer(theSeat)->getLastOutCards(cardsLastOut);
            }
            m_btnIgnore->setEnabled(!cardsLastOut.empty());
        }
        m_btnPostCard->setEnabled(false);
    } else if (state == PLAYER_STATE::ON_CARD_OUT_OVER) {
        std::vector< int32_t > cardsLastOut;
        thePlayer->getLastOutCards(cardsLastOut);
        // 战局保存 Start
        rec_out.emplace_back(std::make_tuple(seat, cardsLastOut, rec_card));
        // 战局保存 End
        if (thePlayer->getCardCount() <= 0) {
            // 牌出完了
            PokerLogic::shard()->over();
            this->m_opGroup->setVisible(false);
            this->m_initGroup->setVisible(false);
            uint8_t master = PokerLogic::shard()->getMasterSeat();
            this->playGameOverAnim(((master != 0 && master != seat) || (master == 0 && seat == 0)), master == seat);
        }
    } else if (state == PLAYER_STATE::ON_INFO_CHANGE) {
        //
    }
}

void PlayLayer::showBottomCard(bool show) {
    static int32_t a[3] = {0};
    PokerLogic::shard()->getBottomCard(a[0], a[1], a[2]);
    m_cardZone->removeAllChildren();
    DelayCall::add([this, show](int tick, bool last, int& count){
        CardUI* ui = CardUI::create();
        ui->setData(a[tick], show);
        ui->setScale(0.7f);
        ui->setPosition(-100.0f + 120.0 * tick, 0.0f);
        m_cardZone->addChild(ui);
    }, 0.2f, 3);
}

void PlayLayer::initUI() {
    m_cardZone->removeAllChildren();
    m_cardZone->setVisible(false);
    m_opGroup->setVisible(false);
    m_initGroup->setVisible(true);
    m_btnMaster->setVisible(false);
    m_btnSkip->setVisible(false);
    m_btnStart->setVisible(true);
    m_btnIgnore->setEnabled(false);
    // 新的一局开始, 删除上一局的数据备份
    rec_bose = 0;
    rec_card.clear();
    rec_out.clear();
}

void PlayLayer::playGameOverAnim(bool selfWin, bool boseWin) {
    if(selfWin) {
        SimpleAudioEngine::getInstance()->playEffect("sound/win.mp3");
    } else {
        SimpleAudioEngine::getInstance()->playEffect("sound/lose.mp3");
    }
    Size visibleSize = Director::getInstance()->getVisibleSize();
    Sprite* sp = Sprite::createWithSpriteFrameName(selfWin ? "gameover/win.png" : "gameover/lose.png");
    sp->setPosition(visibleSize.width * 0.5f, visibleSize.height * 0.5f);
    sp->setScale(0.3f);
    this->addChild(sp, 10000);
    sp->runAction(Sequence::create(EaseElasticOut::create(ScaleTo::create(0.5f, 1.0f))
                                   , DelayTime::create(0.7f)
                                   , CallFunc::create([sp](){ sp->removeFromParent(); })
                                   , NULL)
                  );
    DelayCall::add([this, boseWin](int index, bool finish, int& count) {
        Size visibleSize = Director::getInstance()->getVisibleSize();
        Sprite* sp = Sprite::createWithSpriteFrameName(boseWin ? "gameover/result_dizhusheng.png" : "gameover/result_nongminsheng.png");
        sp->setPosition(visibleSize.width * 0.5f, visibleSize.height * 0.5f);
        sp->setScale(0.3f);
        this->addChild(sp, 10000);
        sp->runAction(Sequence::create(EaseElasticOut::create(ScaleTo::create(0.5f, 1.0f))
                                       , DelayTime::create(0.7f)
                                       , CallFunc::create([sp](){ DialogManager::shared()->showDialog(GameOverUI::create());sp->removeFromParent();  })
                                       , NULL)
                      );
    }, 1.1f);
}

void PlayLayer::onUILoaded() {
    PokerLogic::shard()->init();
    Size visibleSize = Director::getInstance()->getVisibleSize();
    m_btnStart->addClickEventListener([this](Ref* sender) {
        SimpleAudioEngine::getInstance()->playEffect("sound/tips.mp3");
        this->m_opGroup->setVisible(false);
        this->m_initGroup->setVisible(false);
        PokerLogic::shard()->shuffle();
        auto dealCard = [this]() {
            // 每人发 count 张牌, 每张牌间隔 delay 秒
            PokerLogic::shard()->deal(17, 0.01f, [this]() {
                m_initGroup->setVisible(true);
                m_btnMaster->setVisible(true);
                m_btnSkip->setVisible(true);
                m_btnStart->setVisible(false);
                m_cardZone->setVisible(true);
                // 底牌区
                m_cardZone->runAction(FadeIn::create(1.5f));
                showBottomCard(false);
            });
        };
        if (m_players.empty()) {
            DelayCall::add([this, dealCard](int index, bool finish, int& count) {
                // 添加玩家
                std::shared_ptr<PokerPlayer> player = PokerLogic::shard()->playerEnter();
                player->setLocal(index == 0);
                // 绑定成员函数，保存为仿函数
                auto _callback = std::bind(&PlayLayer::onPlayerAction, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
                player->addActionListener(_callback);
                auto ui = PlayerUI::create();
                this->addChild(ui, 100);
                this->m_players[player->getSeat()] = ui;
                ui->setOpacity(0);
                ui->setPlayer(player);
                ui->runAction(FadeIn::create(1.5f));
                if (finish) {
                    dealCard();
                }
            }, 0.2f, PokerLogic::shard()->getMaxPlayerCount());
        } else {
            dealCard();
        }
    });
    m_btnSkip->addClickEventListener([this](Ref* sender) {
        // 不叫? 直接下家随机当地主
        SimpleAudioEngine::getInstance()->playEffect("sound/start/female_voice/female_not_call.mp3");
        m_initGroup->setVisible(false);
        m_opGroup->setVisible(false);
        showBottomCard(true);
        DelayCall::add([this](int tick, bool last, int& count){
            srand((unsigned)time(nullptr));
            rec_bose = (rand() % 2) + 1;
            PokerLogic::shard()->setMasterAndStart(rec_bose);
        }, 1.0f);
    });
    m_btnMaster->addClickEventListener([this](Ref* sender) {
        // 叫地主
        rec_bose = 0;
        SimpleAudioEngine::getInstance()->playEffect("sound/start/female_voice/female_call_dizhu.mp3");
        this->m_players[0]->refreshUI(false);
        PokerLogic::shard()->setMasterAndStart(rec_bose);
        m_initGroup->setVisible(false);
        m_opGroup->setVisible(true);
        m_btnPostCard->setEnabled(false);
        showBottomCard(true);
    });
    m_btnIgnore->addClickEventListener([this](Ref* sender) {
        // 不出
        this->m_players[0]->resetCardSelect();
        this->m_players[0]->cardOut();
        m_opGroup->setVisible(false);
    });
    m_btnReset->addClickEventListener([this](Ref* sender) {
        // 重选
        this->m_players[0]->resetCardSelect();
        this->m_btnPostCard->setEnabled(false);
    });
    m_btnTipCard->addClickEventListener([this](Ref* sender) {
        // 提示
        if(!this->m_players[0]->tipCardSelect()) {
            // 没有能大过对方的
            this->m_opGroup->setVisible(false);
        }
    });
    m_btnPostCard->addClickEventListener([this](Ref* sender) {
        // 出牌(选牌的时候就应该判断过,本按钮可以点击应该就是可以直接出牌)
        this->m_players[0]->cardOut();
        m_opGroup->setVisible(false);
    });
    imgBg->setPosition(visibleSize.width * 0.5f, visibleSize.height * 0.5f);
    imgBg->setScale(MAX(visibleSize.width / 960, visibleSize.height / 540));
    m_cardZone->setPosition(visibleSize.width * 0.5f, visibleSize.height);
    this->addEventListener("CheckUserOutCardType", callfuncO_selector(PlayLayer::whenUserClickCardUI));
    this->addEventListener("OnceMore", callfuncO_selector(PlayLayer::restart));
    this->initUI();
}

void PlayLayer::whenUserClickCardUI(Ref* sender) {
    PlayerUI* playerUI = dynamic_cast<PlayerUI*>(sender);
    if (playerUI) {
        m_btnPostCard->setEnabled(playerUI->canPushCard());
    }
}

// 不换人再来一局
void PlayLayer::restart(Ref* sender) {
    PokerLogic::shard()->onceMore();
    auto iter = m_players.begin();
    while (iter != m_players.end()) {
        iter->second->cleanUI();
        iter++;
    }
    this->initUI();
}


